#include "kbc.h"




/** Initializes the KeyBoard Controller. If 'debug' is not 0 every
 * read or write to the KBC, together with the read or writed data is
 * echoed to the screen. In this mode the function name being executed
 * is printed followed by a ':', add=xx means the I/O address written,
 * and data=xx the data read or written.
 *
 *  A 1 is returned if a mouse is found.
 *
 * The function starts to flush any pending data in the KBC, reading
 * the data register until a timeout is received.
 *
 * Then it enables the KBC mouse interface, send a MouseReset to the
 * mouse and checks for the correct answer (0xFA, 0xAA then 0x00).  If
 * the mouse was detected, data streaming is disabled (StreamDisable),
 * SampleRate is set to 100, Resolution is set to 8 counts/mm, Scaling
 * is set to 1:1, the mouse interrupts generation are enabled at the
 * KBC (not at the PIC!), and data streaming enabled
 * (StreamEnable). All this (but StreamEnable) shouldn't be necessary,
 * as MouseReset is supposed to do it properly.
 *
 * The KBDRate is also set to its maximum speed.
 *
 * Uses write_kbc_cmd(), write_kbc_data(), read_kbc() and write_aux()
 *
 * Example Output generated with debug = 1:
 * <code><pre>
read_kbc: timeout
write_kbc: add=64 data=d4
write_kbc: add=60 data=ff
read_kbc: data=fa
read_kbc: data=aa
read_kbc: data= 0
write_kbc: add=60 data=f5
read_kbc: data=fa
write_kbc: add=64 data=a7
write_kbc: add=64 data=d4
write_kbc: add=60 data=f5
read_kbc: data=fa
write_kbc: add=60 data=f3
read_kbc: data=fa
write_kbc: add=60 data= 0
read_kbc: data=fa
write_kbc: add=64 data=d4
write_kbc: add=60 data=f3
read_kbc: data=fa
write_kbc: add=64 data=d4
write_kbc: add=60 data= a
read_kbc: data=fa
write_kbc: add=64 data=d4
write_kbc: add=60 data=e8
read_kbc: data=fa
write_kbc: add=64 data=d4
write_kbc: add=60 data= 1
read_kbc: data=fa
write_kbc: add=64 data=20
read_kbc: data=45
write_kbc: add=64 data=60
write_kbc: add=60 data=47
read_kbc: timeout
write_kbc: add=60 data=f4
read_kbc: data=fa
write_kbc: add=64 data=a8
write_kbc: add=64 data=d4
write_kbc: add=60 data=f4
read_kbc: data=fa
 * </pre></code>
 */
int kbc_init(int debug)
{
	return 0;
}

/** Disable the mouse, sending a StreamDisable to the mouse, then
 * disables generation of mouse interrupts at the KBC, sends a
 * DisableMouse to the KBC and finnaly disable mouse interrupts at the
 * PIC2
 */
void mouse_disable(void)
{

}

/** Write 'data' to the command register, returning 0 for OK or -1 on
 * timeout.
 * 
 * Uses write_kbc()
 */
int  write_kbc_cmd( unsigned data)
{
	return 0;
}

/** Returns 1 if a DOS mouse driver is installed, 0 if not.
 *  
 * Needed to know if a DOS mouse driver is installed in order
 *  to reinstall it at program end.
 * 
 */
int has_DOS_mouse_ISR()
{
	return 0;
}
  
/** Write 'data' to the data register, returning ACK, Error or -1 on timeout.
 *
 * If a Resend reply is received from the KBC, it retries up to 3 times to
 * write the data.
 *
 * Uses write_kbc() and read_kbc()
 */
int  write_kbc_data( unsigned data)
{
	return 0;
}

/** Send 'cmd' to the mouse, prefacing it with the WriteMouse command
 * to the command register.
 *
 * If a Resend reply is received from the KBC, it retries up to 3 times to
 * write 'cmd', resending the whole sequence.
 *
 * Uses write_kbc_cmd(), write_kbc() and read_kbc()
 */ 
int  write_aux(unsigned cmd)
{
	return 0;
}

/** Returns the data read a the data register.
*
*  Waits for OBF on status register up to KBC_TIMEOUT milliseconds,
*  then reads and returns the data read at the data register. Returns
*  -1 on timeout or transmission error.
*/
int  read_kbc(void)
{
 while(true)
    {
		mili_sleep(KBC_TIMEOUT);
        uchar stat = inportb(STAT_REG);
        if((stat & OBF) != 0)
        {
            uchar data = inportb(DATA_REG);
            if((stat & (PAR_ERR | TO_ERR)) == 0)
                return data;
            else
                return -1;
        }
		mili_sleep(12);
    }
    return -1;

}

/** Write 'data' at IO address 'adr' , returning -1 on error or timeout.
 *
 * Waits for IBF on status register , than writes data to 'adr',
 * return -1 on timeout.
 */
int  write_kbc(unsigned adr, unsigned data)
{
	while(true) 
    {
		mili_sleep(KBC_TIMEOUT);
		unsigned char stat = inportb(STAT_REG);
        if((stat & IBF )== 0){
           outportb(DATA_REG, data);
            return 0;
        }
        mili_sleep(12);
    }
    return -1;
	

}

/** shortky blink all three keyboard LEDs
 *
 */
void blink_leds(void)
{	
//int i = 0;
	//for ( i = 0 ; i < 5 ; i++ )
	//{
		blink_led(NUM_LOCK);
		//Note n= {Mi4, 200}; 
		//play_note(&n);
		blink_led(CAPS_LOCK);
		//Note n1= {Mi4, 200}; 
		//play_note(&n1);
		blink_led(SCROLL_LOCK);
		//Note n2= {Fa4, 200}; 
		//play_note(&n2);
		blink_led(CAPS_LOCK);
		//Note n3= {Sol4, 400}; 
		//play_note(&n3);
		blink_led(NUM_LOCK);
		//Note n4= {Re5, 200}; 
		//play_note(&n4);
	//}


}

/** shortky blink left(1), middle(2) or right(3) keyboard LED
 *
 */
void blink_led(uchar led)
{
	//ligar
	disable_irq(KBD_IRQ);
	write_kbc(DATA_REG,WriteLEDS);
	write_kbc(DATA_REG,led);
	
	mili_sleep(8);
	//desligar
	write_kbc(DATA_REG,WriteLEDS);
	write_kbc(DATA_REG,0x0);
	
	enable_irq(KBD_IRQ);

	
	

}

void beep()
{
	Note n = {Do4, 100};
	play_note(&n);
}
